home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / usr / bin / ecryptfs-setup-private < prev    next >
Text File  |  2009-10-22  |  16KB  |  459 lines

  1. #!/bin/sh
  2. # This script sets up an ecryptfs mount in a user's ~/Private
  3. #
  4. # Originally ecryptfs-setup-pam-wrapped.sh by Michael Halcrow, IBM
  5. #
  6. # Ported for use on Ubuntu by Dustin Kirkland <kirkland@canonical.com>
  7. # Copyright (C) 2008 Canonical Ltd.
  8. # Copyright (C) 2007-2008 International Business Machines
  9. PRIVATE_DIR="Private"
  10. WRAPPING_PASS="LOGIN"
  11. ECRYPTFS_DIR="/home/.ecryptfs"
  12. PW_ATTEMPTS=3
  13. TEXTDOMAIN="ecryptfs-utils"
  14. MESSAGE=`gettext "Enter your login passphrase"`
  15. CIPHER="aes"
  16. KEYBYTES="16"
  17. FNEK=
  18.  
  19. # Zero out user-defined GREP_OPTIONS, such as --line-number
  20. GREP_OPTIONS=
  21.  
  22. usage() {
  23.     echo "
  24. Usage:
  25.  
  26. $0 [-f|--force] [-w|--wrapping] [--nopwcheck] [-n|--no-fnek]
  27.   [-u|--username USER] [-l|--loginpass LOGINPASS]
  28.   [-m|--mountpass MOUNTPASS]
  29.  
  30.  -f, --force      Force overwriting of an existing setup
  31.  -w, --wrapping   Use an independent wrapping passphrase,
  32.                   different from the login passphrase
  33.  -n, --no-fnek    Do not encrypt filenames; If this flag is
  34.                   omitted, and the kernel supports filename
  35.                   encryption, then filenames will be encrypted
  36.  -u, --username   Username for encrypted private mountpoint,
  37.                   defaults to yourself
  38.  -l, --loginpass  Login/Wrapping passphrase for USER,
  39.                   used to wrap MOUNTPASS
  40.  --nopwcheck      Do not check the validity of the specified
  41.                   login password (useful for LDAP user accounts)
  42.  --noautomount    Setup this user such that the encrypted private
  43.                   directory is not automatically mounted on login
  44.  --noautoumount   Setup this user such that the encrypted private
  45.                   directory is not automatically unmounted at
  46.                   logout
  47.  -m, --mountpass  Passphrase for mounting the ecryptfs directory,
  48.                   defaults to randomly generated $KEYBYTES bytes
  49.  -b, --bootstrap  Bootstrap a new user's entire home directory
  50.                   Generates a random mount passphrase, which
  51.           will be wrapped when the new login passphrase
  52.           is set. SHOULD ONLY BE CALLED FROM 'adduser'.
  53.  --undo           Provide instructions on how to undo an
  54.                   encrypted private setup
  55.  
  56.    Be sure to properly escape your parameters according to your
  57.    shell's special character nuances, and also surround the
  58.    parameters by double quotes, if necessary.
  59. "
  60.     exit 1
  61. }
  62.  
  63. undo_msg() {
  64.     echo "
  65. In the event that you want to remove your eCryptfs Private Directory setup,
  66. you will need to very carefully perform the following actions manually:
  67.  
  68.  1. Obtain your Private directory mountpoint
  69.    $ PRIVATE=\`cat ~/.ecryptfs/Private.mnt 2>/dev/null || echo \$HOME/$PRIVATE_DIR\`
  70.  2. Ensure that you have moved all relevant data out of your \$PRIVATE directory
  71.  3. Unmount your encrypted private directory
  72.    $ ecryptfs-umount-private
  73.  4. Make your Private directory writable again
  74.    $ chmod 700 \$PRIVATE
  75.  5. Remove \$PRIVATE, ~/.Private, ~/.ecryptfs
  76.     Note: THIS IS VERY PERMANENT, BE VERY CAREFUL
  77.    $ rm -rf \$PRIVATE ~/.Private ~/.ecryptfs
  78.  6. Uninstall the utilities (this is specific to your Linux distribution)
  79.    $ sudo apt-get remove ecryptfs-utils libecryptfs0
  80. "
  81. }
  82.  
  83. error() {
  84.     echo `gettext "ERROR:"` "$1" 1>&2
  85.     exit 1
  86. }
  87.  
  88. error_testing() {
  89.     rm -f "$1" >/dev/null
  90.     /sbin/umount.ecryptfs_private >/dev/null
  91.     error "$2"
  92.     exit 1
  93. }
  94.  
  95. random_passphrase () {
  96.     bytes=$1
  97.     # Pull $1 of random data from /dev/urandom,
  98.     # and convert to a string of hex digits
  99.     od -x -N $bytes --width=$bytes /dev/urandom | head -n 1 | sed "s/^0000000//" | sed "s/\s*//g"
  100. }
  101.  
  102. filename_encryption_available() {
  103.     version=$(cat /sys/fs/ecryptfs/version 2>/dev/null)
  104.     [ -z "$version" ] && error `gettext "Can't get ecryptfs version, ecryptfs kernel module not loaded?"`
  105.     [ $(($version & 0x100)) -eq 0 ] && return 1
  106.     return 0
  107. }
  108.  
  109. filename_encryption_available && FNEK="--fnek"
  110.  
  111. if [ ! -z "$SUDO_USER" ]; then
  112.     USER="$SUDO_USER"
  113. fi
  114.  
  115. while [ ! -z "$1" ]; do
  116.     case "$1" in
  117.         -u|--username)
  118.                         USER="$2"
  119.             shift 2
  120.         ;;
  121.         -l|--loginpass)
  122.             LOGINPASS="$2"
  123.             shift 2
  124.         ;;
  125.         -m|--mountpass)
  126.             MOUNTPASS="$2"
  127.             shift 2
  128.         ;;
  129.         -w|--wrapping)
  130.             WRAPPING_PASS="INDEPENDENT"
  131.             MESSAGE=`gettext "Enter your wrapping passphrase"`
  132.             shift 1
  133.         ;;
  134.         -f|--force)
  135.             FORCE=1
  136.             shift 1
  137.         ;;
  138.         --nopwcheck)
  139.             NOPWCHECK=1
  140.             shift 1
  141.         ;;
  142.         --noautomount)
  143.             NOAUTOMOUNT=1
  144.             shift 1
  145.         ;;
  146.         --noautoumount)
  147.             NOAUTOUMOUNT=1
  148.             shift 1
  149.         ;;
  150.         --undo)
  151.             undo_msg
  152.             exit 0
  153.         ;;
  154.         -b|--bootstrap)
  155.             [ `whoami` = "root" ] || error `gettext "You must be root to bootstrap encrypt a home directory"`
  156.             BOOTSTRAP=1
  157.             MOUNTPASS=`random_passphrase $KEYBYTES`
  158.             RANDOM_MOUNTPASS=1
  159.             shift 1
  160.         ;;
  161.         -n|--no-fnek)
  162.             FNEK=
  163.             shift 1
  164.         ;;
  165.         *)
  166.             usage
  167.         ;;
  168.     esac
  169. done
  170.  
  171. # Prompt for the USER name, if not on the command line and not in the env
  172. if [ -z "$USER" ]; then
  173.     while [ true ]; do
  174.         echo -n gettext `"Enter the username: "`
  175.         USER=`head -n1`
  176.         echo
  177.         if [ -z "$USER" ]; then
  178.             echo `gettext "ERROR: "` `gettext "You must provide a username"`
  179.             continue
  180.         else
  181.             # Verify that the user exists
  182.             if ! id "$USER" >/dev/null; then
  183.                 echo `gettext "ERROR: "` `gettext "User does not exist"` " [$USER]"
  184.                 continue
  185.             fi
  186.             break
  187.         fi
  188.     done
  189. else
  190.     # Verify that the user exists
  191.     id "$USER" >/dev/null || error `gettext "User does not exist"` "[$USER]"
  192. fi
  193.  
  194. # Obtain USER's primary group
  195. GROUP=$(id -g $USER)
  196.  
  197. # Check if the ecryptfs group exists, and user is member of ecryptfs group
  198. if grep -qs "^ecryptfs:" /etc/group; then
  199.     if ! id "$USER" | grep -qs "\(ecryptfs\)"; then
  200.            error `gettext "User needs to be a member of ecryptfs group"`
  201.     fi
  202. fi
  203.  
  204. # Obtain the user's home directory
  205. HOME=`getent passwd "$USER" | awk -F: '{print $6}'`
  206. if [ ! -d "$HOME" ]; then
  207.     error `gettext "User home directory does not exist"` "[$HOME]"
  208. fi
  209.  
  210. if [ "$BOOTSTRAP" = "1" ]; then
  211.     # If we want to encrypt the entire homedir, we need the .ecryptfs
  212.     # config dir elsewhere, but linked into the homedir
  213.     mkdir -p -m 700 $ECRYPTFS_DIR/$USER/.ecryptfs 
  214.     ln -sf $ECRYPTFS_DIR/$USER/.ecryptfs $HOME/.ecryptfs
  215.     ln -sf $ECRYPTFS_DIR/$USER/.$PRIVATE_DIR $HOME/.$PRIVATE_DIR
  216.     MOUNTPOINT="$HOME"
  217.     CRYPTDIR="$ECRYPTFS_DIR/$USER/.$PRIVATE_DIR"
  218. else
  219.     mkdir -m 700 $HOME/.ecryptfs
  220.     MOUNTPOINT="$HOME/$PRIVATE_DIR"
  221.     CRYPTDIR="$HOME/.$PRIVATE_DIR"
  222. fi
  223.  
  224. # Check for previously setup private directory
  225. if [ -s "$HOME/.ecryptfs/wrapped-passphrase" -a "$FORCE" != "1" ]; then
  226.     error `gettext "wrapped-passphrase file already exists, use --force to overwrite."`
  227. fi
  228. if [ -s "$HOME/.ecryptfs/$PRIVATE_DIR.sig" -a "$FORCE" != "1" ]; then
  229.     error "$PRIVATE_DIR.sig" `gettext "file already exists, use --force to overwrite."`
  230. fi
  231.  
  232. # Check for active mounts
  233. grep -qs "$MOUNTPOINT " /proc/mounts && error "[$MOUNTPOINT]" `gettext "is already mounted"`
  234. grep -qs "$CRYPTDIR " /proc/mounts && error "[$CRYPTDIR]" `gettext "is already mounted"`
  235.  
  236. # Check that the mount point and encrypted directory are empty (skip symlinks).
  237. # Perhaps one day we could provide a migration mode (using rsync or something),
  238. # but this would be VERY hard to do safely.
  239. count=`ls -Al "$MOUNTPOINT" 2>/dev/null | egrep -c "^[drwx-]{10}"`
  240. if [ "$count" != "0" ]; then
  241.     error "$MOUNTPOINT" `gettext "must be empty before proceeding"`
  242. fi
  243. count=`ls -Al "$CRYPTDIR" 2>/dev/null | egrep -c "^[dlrwx-]{10}"`
  244. if [ "$count" != "0" ]; then
  245.     error "$CRYPTDIR" `gettext "must be empty before proceeding"`
  246. fi
  247.  
  248. stty_orig=`stty -g`
  249. # Prompt for the LOGINPASS, if not on the command line and not in the env
  250. if [ -z "$LOGINPASS" ] && [ "$BOOTSTRAP" != "1" ]; then
  251.     tries=0
  252.     while [ $tries -lt $PW_ATTEMPTS ]; do
  253.         stty -echo
  254.         echo -n "$MESSAGE: "
  255.         LOGINPASS=`head -n1`
  256.         stty $stty_orig
  257.         echo
  258.         if [ $WRAPPING_PASS != "LOGIN" -o ! -x /sbin/unix_chkpwd ]; then
  259.             # If we can't check the accuracy of the user's entered
  260.             # passphrase, force them to type it twice (matching)
  261.             stty -echo
  262.             echo -n "$MESSAGE (again): "
  263.             LOGINPASS2=`head -n1`
  264.             stty $stty_orig
  265.             echo
  266.             if [ "$LOGINPASS" != "$LOGINPASS2" ]; then
  267.                 echo `gettext "ERROR:"` `gettext "Wrapping passphrases must match"`
  268.             else
  269.                 break
  270.             fi
  271.             tries=$(($tries + 1))
  272.             continue
  273.         fi
  274.         if [ -z "$LOGINPASS" ]; then
  275.             echo `gettext "ERROR:"` `gettext "You must provide a login passphrase"`
  276.             tries=$(($tries + 1))
  277.         else
  278.             if [ "$NOPWCHECK" = "1" ]; then
  279.                 echo `gettext "INFO:"` `gettext "Skipping password verification"`
  280.                 break
  281.             else
  282.                 if printf "%s\0" "$LOGINPASS" | /sbin/unix_chkpwd "$USER" nullok; then
  283.                     break
  284.                 else
  285.                     echo `gettext "ERROR:"` `gettext "Your login passphrase is incorrect"`
  286.                     tries=$(($tries + 1))
  287.                 fi
  288.             fi
  289.         fi
  290.     done
  291.     if [ $tries -ge $PW_ATTEMPTS ]; then
  292.         error `gettext "Too many incorrect password attempts, exiting"`
  293.     fi
  294. fi
  295.  
  296. # Prompt for the MOUNTPASS, if not on the command line and not in the env
  297. if [ -z "$MOUNTPASS" ]; then
  298.     tries=0
  299.     while [ $tries -lt $PW_ATTEMPTS ]; do
  300.         stty -echo
  301.         echo -n `gettext "Enter your mount passphrase [leave blank to generate one]: "`
  302.         MOUNTPASS=`head -n1`
  303.         stty $stty_orig
  304.         echo
  305.         if [ -z "$MOUNTPASS" ]; then
  306.             MOUNTPASS=`random_passphrase $KEYBYTES`
  307.             RANDOM_MOUNTPASS=1
  308.             break
  309.         else
  310.             stty -echo
  311.             echo -n `gettext "Enter your mount passphrase (again): "`
  312.             MOUNTPASS2=`head -n1`
  313.             stty $stty_orig
  314.             echo
  315.             if [ "$MOUNTPASS" != "$MOUNTPASS2" ]; then
  316.                 echo `gettext "ERROR:"` `gettext "Mount passphrases do not match"`
  317.                 tries=$(($tries + 1))
  318.             else
  319.                 break
  320.             fi
  321.         fi
  322.     done
  323.     if [ $tries -ge $PW_ATTEMPTS ]; then
  324.         error `gettext "Too many incorrect passphrase attempts, exiting"`
  325.     fi
  326. fi
  327.  
  328. echo
  329. echo "************************************************************************"
  330. echo `gettext "YOU SHOULD RECORD YOUR MOUNT PASSPHRASE AND STORE IT IN A SAFE LOCATION."`
  331. echo "  ecryptfs-unwrap-passphrase ~/.ecryptfs/wrapped-passphrase"
  332. echo `gettext "THIS WILL BE REQUIRED IF YOU NEED TO RECOVER YOUR DATA AT A LATER TIME."`
  333. echo "************************************************************************"
  334. echo
  335.  
  336. ###############################################################################
  337.  
  338. # Setup private directory in home
  339. mkdir -m 700 -p "$CRYPTDIR" || error `gettext "Could not create crypt directory"` "[$CRYPTDIR]"
  340. mkdir -m 700 -p "$MOUNTPOINT" || error `gettext "Could not create mount directory"` "[$MOUNTPOINT]"
  341. ln -sf /usr/share/ecryptfs-utils/ecryptfs-mount-private.txt "$MOUNTPOINT"/README.txt
  342. ln -sf /usr/share/ecryptfs-utils/ecryptfs-mount-private.desktop "$MOUNTPOINT"/Access-Your-Private-Data.desktop
  343. chmod 500 "$MOUNTPOINT"
  344.  
  345. # Setup ~/.ecryptfs directory
  346. if [ "$NOAUTOMOUNT" = "1" ]; then
  347.     echo `gettext "INFO:"` "$HOME/$PRIVATE_DIR" `gettext "will not be mounted on login"`
  348. else
  349.     touch $HOME/.ecryptfs/auto-mount || error `gettext "Could not setup ecryptfs auto-mount"`
  350. fi
  351. if [ "$NOAUTOUMOUNT" = "1" ]; then
  352.     echo `gettext "INFO:"` "$HOME/$PRIVATE_DIR" `gettext "will not be unmounted on logout"`
  353. else
  354.     touch $HOME/.ecryptfs/auto-umount || error `gettext "Could not setup ecryptfs auto-umount"`
  355. fi
  356.  
  357. if [ "$WRAPPING_PASS" = "LOGIN" ]; then
  358.     rm -f $HOME/.ecryptfs/wrapping-independent || error `gettext "Could not remove ecryptfs wrapping-independent"`
  359. else
  360.     touch $HOME/.ecryptfs/wrapping-independent || error `gettext "Could not setup ecryptfs wrapping-independent"`
  361. fi
  362.  
  363.  
  364. # Backup any existing wrapped-passphrase or sig files; we DO NOT destroy this
  365. timestamp=`date +%Y%m%d%H%M%S`
  366. for i in "$HOME/.ecryptfs/wrapped-passphrase" "$HOME/.ecryptfs/$PRIVATE_DIR.sig"; do
  367.     if [ -s "$i" ]; then
  368.         mv -f "$i" "$i.$timestamp" || error `gettext "Could not backup existing data"` "[$i]"
  369.     fi
  370. done
  371.  
  372. # Setup wrapped-passphrase file
  373. u=`umask`
  374. umask 377
  375. if [ "$BOOTSTRAP" = "1" ]; then
  376.     # This will be wrapped by pam_ecryptfs's chauthtok as soon as the user
  377.     # chooses a password.  Until that happens (hopefully soon), standard
  378.     # file permissions (600) are all that's protecting it.  Write it to
  379.     # ramdisk, to keep it from leaking to the hard-drive.
  380.     temp=`mktemp /dev/shm/.ecryptfs-XXXXXX`
  381.     printf "%s" "$MOUNTPASS" > "$temp"
  382.     mv "$temp" "/dev/shm/.ecryptfs-$USER"
  383. else
  384.     printf "%s\n%s" "$MOUNTPASS" "$LOGINPASS" | ecryptfs-wrap-passphrase "$HOME/.ecryptfs/wrapped-passphrase" - || error `gettext "Could not wrap passphrase"`
  385. fi
  386. umask $u
  387.  
  388. # Add the passphrase to current keyring
  389. # On subsequent logins, this should be handled by "pam_ecryptfs.so unwrap"
  390. response=`printf "%s" "$MOUNTPASS" | ecryptfs-add-passphrase $FNEK -`
  391. if [ $? -ne 0 ]; then
  392.     error `gettext "Could not add passphrase to the current keyring"`
  393. fi
  394. sig=`echo "$response" | grep "Inserted auth tok" | sed "s/^.*\[//" | sed "s/\].*$//"`
  395. if ! echo "$sig" | egrep -qs "^[0-9a-fA-F]{$KEYBYTES,$KEYBYTES}$"; then
  396.     error `gettext "Could not obtain the key signature"`
  397. fi
  398. temp=`mktemp`
  399. echo "$sig" > "$temp" || error `gettext "Could not create signature file"` "[$HOME/.ecryptfs/$PRIVATE_DIR.sig]"
  400. mv "$temp" "$HOME/.ecryptfs/$PRIVATE_DIR.sig"
  401. temp=`mktemp`
  402. echo "$MOUNTPOINT" > "$temp" || error `gettext "Could not create mountpoint file"` "[$HOME/.ecryptfs/$PRIVATE_DIR.mnt]"
  403. mv "$temp" "$HOME/.ecryptfs/$PRIVATE_DIR.mnt"
  404.  
  405. echo
  406. echo `gettext "Done configuring."`
  407. echo
  408.  
  409. # Skip the tests if we're in bootstrap mode, but exit with the encrypted
  410. # homedir mounted
  411. if [ "$BOOTSTRAP" = "1" ]; then
  412.     # Force the mount here, since the root user has the key loaded,
  413.     # and the calling 'adduser' is about to copy over /etc/skel
  414.     # NOTE: it is the responsibility of 'adduser' to unmount!
  415.     # And ensure that $USER owns the files/dirs we've created as root
  416.     chown $USER:$GROUP "$CRYPTDIR" /dev/shm/.ecryptfs-$USER
  417.     chown -R $USER:$GROUP $ECRYPTFS_DIR/$USER
  418.     chown -R $USER:$GROUP $MOUNTPOINT
  419.     if [ "$FNEK" = "--fnek" ]; then
  420.         fnek_sig=`tail -n 1 "$HOME/.ecryptfs/$PRIVATE_DIR.sig"`
  421.         sig=`head -n 1 "$HOME/.ecryptfs/$PRIVATE_DIR.sig"`
  422.         sig_opt="ecryptfs_sig=$sig,ecryptfs_fnek_sig=$fnek_sig"
  423.     else
  424.         sig_opt="ecryptfs_sig=$sig"
  425.     fi
  426.     # Do the mount, and provide some helpful symlinks
  427.     mount -i -t ecryptfs -o "rw,$sig_opt,ecryptfs_cipher=$CIPHER,ecryptfs_key_bytes=$KEYBYTES" "$CRYPTDIR" "$MOUNTPOINT" || error "Could not mount"
  428.     ln -sf $ECRYPTFS_DIR/$USER/.ecryptfs $MOUNTPOINT/.ecryptfs
  429.     ln -sf $ECRYPTFS_DIR/$USER/.$PRIVATE_DIR $MOUNTPOINT/.$PRIVATE_DIR
  430.     chown -R $USER:$GROUP $ECRYPTFS_DIR/$USER
  431.     chown -R $USER:$GROUP $MOUNTPOINT
  432.     exit 0
  433. fi
  434.  
  435. # Now let's perform some basic mount/write/umount/read sanity testing...
  436. echo `gettext "Testing mount/write/umount/read..."`
  437. /sbin/mount.ecryptfs_private || error `gettext "Could not mount private ecryptfs directory"`
  438. temp=`mktemp "$MOUNTPOINT/ecryptfs.test.XXXXXX"` || error_testing "$temp" `gettext "Could not create empty file"`
  439. random_data=`head -c 16000 /dev/urandom | od -x` || error_testing "$temp" `gettext "Could not generate random data"`
  440. echo "$random_data" > "$temp" || error_testing "$temp" `gettext "Could not write encrypted file"`
  441. md5sum1=`md5sum "$temp"` || error_testing "$temp" `gettext "Could not read encrypted file"`
  442. /sbin/umount.ecryptfs_private || error_testing "$temp" `gettext "Could not unmount private ecryptfs directory"`
  443. /sbin/mount.ecryptfs_private || error_testing "$temp" `gettext "Could not mount private ecryptfs directory (2)"`
  444. md5sum2=`md5sum "$temp"` || error_testing "$temp" `gettext "Could not read encrypted file (2)"`
  445. rm -f "$temp"
  446. # Use ecryptfs-umount-private on the final run, to clear the used keys
  447. # out of the keyring
  448. ecryptfs-umount-private || error_testing "$temp" `gettext "Could not unmount private ecryptfs directory (2)"`
  449. if [ "$md5sum1" != "$md5sum2" ]; then
  450.     error `gettext "Testing failed."`
  451. else
  452.     echo `gettext "Testing succeeded."`
  453. fi
  454.  
  455. echo
  456. echo `gettext "Logout, and log back in to begin using your encrypted directory."`
  457. echo
  458. exit 0
  459.